package com.whz.gateway.configure;

import com.google.common.collect.Lists;
import com.whz.gateway.common.constants.GatewayConstant;
import com.whz.gateway.common.util.GatewayJsonUtils;
import com.whz.generic.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.ApiResourceController;
import springfox.documentation.swagger.web.InMemorySwaggerResourcesProvider;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author whz
 * @see ApiResourceController
 */
@Slf4j
@Primary
@Component
@RefreshScope
public class SwaggerResourceConfigure implements SwaggerResourcesProvider {

    private static final Pattern COMPILE = Pattern.compile("/*", Pattern.LITERAL);
    @Resource
    private RouteLocator routeLocator;

    @Resource
    private GatewayProperties gatewayProperties;

    @Override
    public List<SwaggerResource> get() {
        log.info("gateway router properties :{}", GatewayJsonUtils.toJson(gatewayProperties.getRoutes()));

        List<SwaggerResource> resources = Lists.newArrayList();
        List<String> routes = Lists.newArrayList();
        //取出Spring Cloud Gateway中的router
        routeLocator.getRoutes().map(Route::getId).subscribe(routes::add);
        log.info("gateway router locators :{}", GatewayJsonUtils.toJson(routes));
        //结合application.yml中的路由配置，只获取有效的route节点
        gatewayProperties.getRoutes().stream()
                         .filter(r -> routes.contains(r.getId()))
                         .forEach(r -> r.getPredicates().stream()
                                        .filter(p -> "path".equalsIgnoreCase(p.getName()))
                                        .map(p -> swaggerResource(r.getId(), getLocation(p)))
                                        .forEach(resources::add));

        SpringUtils.getBean(InMemorySwaggerResourcesProvider.class)
                   .ifPresent(provider -> resources.addAll(provider.get()));

        Collections.sort(resources);
        return resources;
    }

    private static String getLocation(PredicateDefinition p) {
        return COMPILE.matcher(p.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + '0'))
                      .replaceAll(GatewayConstant.SWAGGER_PATH);
    }

    private static SwaggerResource swaggerResource(String name, String location) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("3.0");
        return swaggerResource;
    }
}